use std::fs;
use anyhow::Ok;
use csv::Reader;
// 序列化、反序列化
use serde::{Serialize, Deserialize};
use serde_json::{Value};

use crate::cli::OutputFormat;


// 声明序列化、反序列化宏, 使该结构体自动实现序列化、反序列化功能
#[derive(Debug, Deserialize, Serialize)]
// 声明结构体内的字段默认按照Pascal命名进行命名
#[serde(rename_all = "PascalCase")]
struct Player {
    name: String,
    position: String,
    // 当字段名不是标准的Pascal风格时, 例如: dob的Pascal命名为Dob
    // 可以单独指定某个字段的名称
    #[serde(rename = "DOB")]
    dob: String,
    nationality: String,
    // 单独指定某个字段的名称
    #[serde(rename = "Kit Number")]
    kit: u8,
}


pub fn process_csv(input: &str, output: String, format: OutputFormat) -> anyhow::Result<()> {
    // 通用csv处理, 不依赖具体格式的结构体: 可以将其转换为其他任意格式, 例如: yaml、json、toml等
    let mut reader = Reader::from_path(input)?;
    let headers = reader.headers()?.clone();
    let mut ret = Vec::with_capacity(128);
    for result in reader.records() {
        let record = result?;
        // headers.iter() -> 使用headers的迭代器
        // record.iter() -> 使用record的迭代器
        // zip() -> 将两个迭代器合并, 返回一个元组迭代器, 最终会得到: [(header, record), ...]
        // collect::<Value>() -> 将元组迭代器转换为 Json Value
        let json_value = headers.iter().zip(record.iter()).collect::<Value>();
        ret.push(json_value);
        
        // 上面的函数式编程代码等价于:
        // for i in 0..headers.len() {
        //     let json_value = serde_json::json!({
        //         headers[i]: record[i]
        //     });
        //     println!("{:?}", json_value);
        //     ret.push(json_value);
        // }
    }

    // 序列化为最终的输出格式
    let content = match format {
        OutputFormat::Json => serde_json::to_string_pretty(&ret)?,
        OutputFormat::Yaml => serde_yaml::to_string(&ret)?,
    };
    // 写入参数指定的output文件中
    fs::write(output, content)?;

    Ok(())
}


pub fn process_csv_v1(input: &str, output: &str) -> anyhow::Result<()> {
    // 处理csv子命令, 因为强绑定了Player结构体, 所以该方法兼容其他输出格式
    let mut reader = Reader::from_path(input)?;
    let mut ret = Vec::with_capacity(128);
    for result in reader.deserialize() {
        // 这里必须强制指明类型为Player, 否则result不会自动转换为Player类型. 输出结果为: ()
        // let record = result?;
        let record: Player = result?;
        ret.push(record);
    }
    
    // 序列化为json字符串
    let json = serde_json::to_string_pretty(&ret)?;
    // 写入参数指定的output文件中
    fs::write(output, json)?;

    Ok(())
}